home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ldb.zip / SBINDER.CPP < prev    next >
C/C++ Source or Header  |  1991-10-18  |  11KB  |  545 lines

  1. /*
  2.  
  3.     sbinder.cpp
  4.     10-18-91
  5.     Streamable Binder: Loose Data Binder v 1.4
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.  
  11.     PSW / Power SoftWare
  12.     P.O. Box 10072
  13.     McLean, Virginia 22102 8072 USA
  14.  
  15.     John Small
  16.     Voice: (703) 759-3838
  17.     CIS: 73757,2233
  18.  
  19. */
  20.  
  21.  
  22. #include <string.h>
  23. #include "sbinder.hpp"
  24.  
  25.  
  26. void Streamable::lserror(const char *msg, unsigned id)
  27. {
  28.     if (streamDebug)
  29.         cerr << endl
  30.             << "Class id: " << setw(6) << id
  31.             <<  "   stream error - "
  32.             << msg << endl;
  33. }
  34.  
  35. void Streamable::serror(const char *msg)
  36. {
  37.     if (streamDebug)
  38.         cerr << endl
  39.             <<"Class id: " << setw(6) << id
  40.             << "    &instance:   "
  41.             << (void *) this << endl
  42.             <<  "Stream error - "
  43.             << msg << endl;
  44. }
  45.  
  46. void Streamable::swarn(const char *msg)
  47. {
  48.     if (streamDebug)
  49.         cerr << endl
  50.             << "Class id: " << setw(6) << id
  51.             << "    &instance:   "
  52.             << (void *) this << endl
  53.             <<  "Stream warning - "
  54.             << msg << endl;
  55. }
  56.  
  57.  
  58. #pragma argsused
  59. StreamablE Streamable::load(istream& is,
  60.     StreamablE InstancE)
  61.     { return InstancE; }
  62.  
  63. int  Streamable::refDebug = 0;
  64. int  Streamable::streamDebug = 0;
  65. char Streamable::memberTermChar = '\n';
  66.  
  67. #pragma argsused
  68. Streamable::Streamable(StreamableClassRegistry& dummy,
  69.     unsigned id)
  70. {
  71.     parenT = voiD0;
  72.     this->id = id;
  73.     refCount = streamCount = 0;
  74.     streamPos = 0L;
  75. }
  76.  
  77. void Streamable::registerClass(unsigned id,
  78.         StreamablE (*loader)(istream& is,
  79.         StreamablE InstancE))
  80. {
  81.     SCRegistry.registerClass(id,loader);
  82. }
  83.  
  84. unsigned Streamable::restream()
  85. {
  86.     unsigned underFlow = (streamPos? 
  87.         refCount - streamCount : 0);
  88.     
  89.     streamCount = 0; 
  90.     streamPos = 0L;
  91.     if (underFlow)
  92.         swarn("restream: streamed less than "
  93.             "referenced");    
  94.     return underFlow;
  95. }
  96.  
  97. unsigned Streamable::unlink(voiD P)
  98. {
  99.     if (refDebug)
  100.         if (refCount)
  101.             cerr << endl
  102.             << "Class id: " << setw(6) << id
  103.             << "    &instance:   "
  104.             << (void *) this << endl
  105.             <<  "Unlinking, starting refCount: "
  106.             << refCount << endl;
  107.         else
  108.             cerr << endl
  109.             << "Class id: " << setw(6) << id
  110.             << "    &instance:   "
  111.             << (void *) this << endl
  112.             <<  "unlink() underflow" << endl;
  113.     if (refCount)
  114.         --refCount;
  115.     if (parenT == P || !refCount)
  116.         parenT = voiD0;
  117.     return refCount;
  118. }
  119.  
  120. StreamablE Streamable::link(voiD P)
  121. {
  122.     if (refCount >= UINT_MAX)  {
  123.         if (refDebug)
  124.             cerr << endl
  125.             << "Class id: " << setw(6) << id
  126.             << "    &instance:   "
  127.             << (void *) this << endl
  128.             <<  "link() overflow" << endl;
  129.         return StreamablE0;
  130.     }
  131.     refCount++;
  132.     if (!parenT && P)
  133.         parenT = P;
  134.     if (refDebug)
  135.         cerr << endl
  136.             << "Class id: " << setw(6) << id
  137.             << "    &instance:   "
  138.             << (void *) this << endl
  139.             <<  "Adding link, new refCount: "
  140.             << refCount << endl;
  141.     return this;
  142. }
  143.  
  144. ostream& endm(ostream& os)
  145. {
  146.     return os << Streamable::memberTermChar
  147.         << flush;
  148. }
  149.  
  150. istream& nextm(istream& is)
  151. {
  152.     is.get();
  153.     return is;
  154. }
  155.  
  156. int SBinder::Dfree(voiD D)
  157. {
  158.     if (D)  {
  159.         if (!((StreamablE)D)->RefCount())
  160.             delete (StreamablE) D;
  161.         return 1;
  162.     }
  163.     return 0;
  164. }
  165.  
  166. int SBinder::Dattach(voiD D)
  167. {
  168.     return ((((StreamablE)D)->link(this))? 1 : 0);
  169. }
  170.  
  171. void SBinder::Ddetach(voiD D)
  172. {
  173.     ((StreamablE)D)->unlink(this);
  174. }
  175.  
  176. ostream& SBinder::store(ostream& os)
  177. {
  178.     unsigned i;
  179.  
  180.     os << maxNodes << endm << limit << endm
  181.         << delta << endm << nodes << endm
  182.         << curNode << endm << flags << endm
  183.         << FncPtrToID((GenericFnC)comparE) << endm;
  184.     if (!os)
  185.         serror("unable to store Streamable Binder");
  186.     else for (i = 0; i < nodes; i++)
  187.         Dstore(os,atGet(i));
  188.     return os;
  189. }
  190.  
  191. StreamablE SBinder::load(istream& is, StreamablE InstancE)
  192. {
  193.     unsigned i, maxNodes, limit, delta, nodes, curNode;
  194.     unsigned flags;
  195.     unsigned comparEID;
  196.  
  197.     is >> maxNodes >> nextm >> limit >> nextm
  198.         >> delta >> nextm >> nodes >> nextm
  199.         >> curNode >> nextm >> flags >> nextm
  200.         >> comparEID >> nextm;
  201.     if (!is)  {
  202.         lserror("unable to load Streamable Binder "
  203.             "header data",
  204.             ID_CLASS);
  205.         return StreamablE0;
  206.     }
  207.     flags |= BDR_OK_FREE; // reloaded nodes are dynamic!
  208.     if (!InstancE)
  209.         if ((InstancE = (StreamablE)
  210.             new SBinder(UNIQUE_STREAMABLE))
  211.             == StreamablE0)  {
  212.             lserror("unable to construct "
  213.                 "Streamable Binder for "
  214.                 "loading",ID_CLASS);
  215.             return StreamablE0;
  216.         }
  217.     ((SBindeR)InstancE)->construct(flags,maxNodes,
  218.         limit,delta);
  219.     StreamablE D;
  220.     for (i = 0; i < nodes; i++)
  221.         ((SBindeR)InstancE)->insQ(
  222.             ((SBindeR)InstancE)->Dload(is));
  223.     ((SBindeR)InstancE)->setCurNode(curNode);
  224.     ((SBindeR)InstancE)->setComparE((BDRcomparE)
  225.         IDtoFncPtr(comparEID));
  226.     return InstancE;
  227. }
  228.  
  229. void SBinder::Dstore(ostream& os, const voiD D)
  230.     { os << (StreamablE) D; }
  231.  
  232. voiD SBinder::Dload(istream& is)
  233. {
  234.     StreamablE InstancE = StreamablE0;
  235.     
  236.     is >> InstancE;
  237.     return (voiD) InstancE;
  238. }
  239.  
  240. unsigned SBinder::restream()
  241. {
  242.     unsigned result = Streamable::restream();
  243.     for (unsigned i = 0; i < nodes; i++)
  244.         ((StreamablE)atGet(i))->restream();
  245.     return result;
  246. }
  247.  
  248. SBinder::~SBinder()
  249. {
  250.     if (flags & BDR_OK_FREE)
  251.         allFree();
  252.     else
  253.         allDel();
  254. }
  255.  
  256.  
  257. StreamableClassRegistry SCRegistry;
  258.  
  259. int StreamableClassRegistry::debug = 0;
  260.  
  261. void StreamableClassRegistry::error(char *msg, unsigned id,
  262.     StreamablE InstancE)
  263. {
  264.     if (debug)
  265.         cerr << endl
  266.             << "Class id: " << setw(6) << id
  267.             << "    &instance:   "
  268.             << (void *) InstancE << endl
  269.             << "ClassRegistry error - "
  270.             << msg << endl;
  271. }
  272.  
  273. void StreamableClassRegistry::warn(char *msg, unsigned id,
  274.     StreamablE InstancE)
  275. {
  276.     if (debug)
  277.         cerr << endl
  278.             << "Class id: " << setw(6) << id
  279.             << "    &instance:   "
  280.             << (void *) InstancE << endl
  281.             << "ClassRegistry warning - "
  282.             << msg << endl;
  283. }
  284.  
  285. unsigned StreamableClassRegistry::restream()
  286. {
  287.  
  288.     unsigned underFlow = InstanceLinks.Nodes();
  289.     IHRecorD R;
  290.  
  291.     for (unsigned i = 0; i < underFlow; i++)  {
  292.         R = (IHRecorD) InstanceLinks.atGet(i);
  293.         warn("Restream: holding pen under-linked",
  294.             R->InstancE->id,R->InstancE);
  295.     }
  296.     InstanceLinks.allFree();
  297.     return underFlow;
  298. }
  299.  
  300. void StreamableClassRegistry::registerClass(unsigned id,
  301.     StreamablE (*loader) (istream& is,
  302.     StreamablE InstancE))
  303. {
  304.     unsigned i;
  305.  
  306.     for (i = 0; i < ClassRecords.Nodes(); i++)
  307.         if (((SCRecorD)ClassRecords[i])->id
  308.             == id)
  309.             break;
  310.     if (i < ClassRecords.Nodes())
  311.         if (((SCRecorD)ClassRecords[i])->load
  312.             == loader)  {
  313.             warn("multiple registration of"
  314.                 " loader",id);
  315.             return;
  316.         }
  317.         else  {
  318.             error("id conflict: ",id);
  319.             return;
  320.         }
  321.     SCRecorD R = new StreamableClassRecord(id,loader);
  322.     if (!R)
  323.         error("class record memory exhausted",
  324.             id);
  325.     else if (!ClassRecords.insQ(R))  {
  326.         error("class record can't be queued",
  327.             id);
  328.         delete R;
  329.     }
  330. }
  331.  
  332. void StreamableClassRegistry::forgetClasses()
  333. {
  334.     ClassRecords.allFree();
  335.     InstanceLinks.allFree();
  336. }
  337.  
  338. istream& StreamableClassRegistry::get(istream& is,
  339.     StreamablE& InstancE)
  340. {
  341.     unsigned id, refCount, i;
  342.     long streamPos;
  343.     IHRecorD R;
  344.  
  345.     InstancE = StreamablE0;
  346.     if (!(is >> id >> nextm))  {
  347.         error("unable to read id");
  348.         return is;
  349.     }
  350.     if (id == ID_StreamableRef)  {
  351.         // link to previously loaded Instance
  352.         if (!(is >> streamPos >> nextm))  {
  353.             error("unable to read streamPos");
  354.             return is;
  355.         }
  356.         for (i = 0; i < InstanceLinks.Nodes(); i++)
  357.             if ((R = (IHRecorD)InstanceLinks[i])
  358.                 ->streamPos == streamPos)  {
  359.                 // found saved instance!
  360.                 InstancE = R->InstancE;
  361.                 if (R->refCount <= ++R->streamCount)
  362.                     // discard when done!
  363.                     InstanceLinks.atDel(i);
  364.                 break;
  365.             }
  366.         if (!InstancE)
  367.             error("unable to establish link to"
  368.                 " previously loaded class",
  369.                 id);
  370.     }
  371.     else  {  // load instance
  372.         streamPos = is.tellg();
  373.         if (!(is >> refCount >> nextm))  {
  374.             error("unable to read refCount",id);
  375.             return is;
  376.         }
  377.         for (i = 0; i < ClassRecords.Nodes(); i++)
  378.             if (((SCRecorD)ClassRecords[i])->id
  379.                 == id)
  380.                 break;
  381.         if (i >= ClassRecords.Nodes())  {
  382.             error("attempted load of unknown "
  383.                 "class",id);
  384.             return is;
  385.         }
  386.         if ((InstancE = (*((SCRecorD)
  387.             ClassRecords[i])->load)
  388.             (is,StreamablE0)) == StreamablE0)
  389.         {
  390.             error("unable to load instance",id);
  391.             return is;
  392.         }
  393.         if (refCount > 1)  {
  394.             // 1st of many save in holding pen
  395.             R = new InstanceHoldingRecord
  396.                 (InstancE,refCount,streamPos);
  397.             if (!R)
  398.                 error("class holding record"
  399.                 " memory exhausted,"
  400.                 " id: ",id,InstancE);
  401.             else if (!InstanceLinks.insQ(R))  {
  402.                 error("unable to hold "
  403.                     "instance for "
  404.                     "multiple links ",
  405.                     id,InstancE);
  406.                 delete R;
  407.             }
  408.         }
  409.     }
  410.     return is;
  411. }
  412.  
  413. ostream& StreamableClassRegistry::put(ostream& os,
  414.     StreamablE InstancE)
  415. {
  416.     unsigned id, i;
  417.     long tpos;
  418.  
  419.     if (!InstancE)
  420.         return os;
  421.     id = InstancE->id;
  422.     for (i = 0; i < ClassRecords.Nodes(); i++)
  423.         if (((SCRecorD)ClassRecords[i])->id == id)
  424.             break;
  425.     if (i >= ClassRecords.Nodes())  {
  426.         error("attempted store of unknown class: ",
  427.             id);
  428.     }
  429.     else if (InstancE->refCount <= InstancE->streamCount)
  430.         error("more attempting stores than links",
  431.             id,InstancE);
  432.     else {
  433.         InstancE->streamCount++;
  434.         if (InstancE->streamPos)  {
  435.               // already stored!
  436.             if (!(os << ID_StreamableRef << endm
  437.                 << InstancE->streamPos
  438.                 << endm))
  439.                 error("unable to store "
  440.                     "multiple reference",
  441.                     id,InstancE);
  442.         }
  443.         else if (!(os << id << endm))
  444.             error("unable to store id",
  445.                 id,InstancE);
  446.         else  {
  447.             InstancE->streamPos = os.tellp(); 
  448.             if (!(os << InstancE->refCount
  449.                 << endm))
  450.                 error("unable to store "
  451.                     "refCount ",id,
  452.                     InstancE);
  453.             else
  454.                 InstancE->store(os);
  455.         }
  456.     }
  457.     return os << flush;
  458. }
  459.  
  460.  
  461. StreamableFncPtrRegistry SFPRegistry;
  462.  
  463. int StreamableFncPtrRegistry::debug;
  464.  
  465. void StreamableFncPtrRegistry::error(char *msg, unsigned id)
  466. {
  467.     if (debug)
  468.         cerr << "FncPtrRegistry error - "
  469.             << msg << id << endl;
  470. }
  471.  
  472. void StreamableFncPtrRegistry::warn(char *msg, unsigned id)
  473. {
  474.     if (debug)
  475.         cerr << "FncPtrRegistry warning - "
  476.             << msg << id << endl;
  477.  
  478. }
  479.  
  480. void StreamableFncPtrRegistry::registerFunction(unsigned id,
  481.     GenericFnC fnC)
  482. {
  483.     unsigned i;
  484.  
  485.     for (i = 0; i < FncPtrRecords.Nodes(); i++)
  486.         if (((SFPRecorD)FncPtrRecords[i])->id == id)
  487.             break;
  488.     if (i < FncPtrRecords.Nodes())
  489.         if (((SFPRecorD)FncPtrRecords[i])->fnC
  490.             == fnC)
  491.         {
  492.             warn("attempted multiple"
  493.                 " registration"
  494.                 " of function pointer: ",
  495.                 id);
  496.             return;
  497.         }
  498.         else {
  499.             error("id conflict: ",id);
  500.             return;
  501.         }
  502.     SFPRecorD R = new StreamableFncPtrRecord(id,fnC);
  503.     if (!R)
  504.         error("fncPtr memory exhausted, id: ",id);
  505.     else if (!FncPtrRecords.insQ(R))  {
  506.         error("fncPtr record can't be queued, id: ",
  507.             id);
  508.         delete R;
  509.     }
  510. }
  511.  
  512.  
  513. GenericFnC StreamableFncPtrRegistry::FnC(unsigned id)
  514. {
  515.     unsigned i;
  516.  
  517.     for (i = 0; i < FncPtrRecords.Nodes(); i++)
  518.         if (((SFPRecorD)FncPtrRecords[i])->id == id)
  519.             break;
  520.     if (i >= FncPtrRecords.Nodes())  {
  521.         error("unknown fncPtr: ",id);
  522.         return GenericFnC0;
  523.     }
  524.     else
  525.         return ((SFPRecorD)FncPtrRecords[i])->fnC;
  526. }
  527.  
  528. unsigned StreamableFncPtrRegistry::ID(GenericFnC fnC)
  529. {
  530.     unsigned i;
  531.  
  532.     for (i = 0; i < FncPtrRecords.Nodes(); i++)
  533.         if (((SFPRecorD)FncPtrRecords[i])->fnC
  534.             == fnC)
  535.             break;
  536.     if (i >= FncPtrRecords.Nodes())  {
  537.         error("unknown fncPtr: ",
  538.             ID_UnknownGenericFnC);
  539.         return ID_UnknownGenericFnC;
  540.     }
  541.     else
  542.         return ((SFPRecorD)FncPtrRecords[i])->id;
  543. }
  544.  
  545.